home *** CD-ROM | disk | FTP | other *** search
/ Sprite 1984 - 1993 / Sprite 1984 - 1993.iso / src / kernel / raid / devRaid.c < prev    next >
Encoding:
C/C++ Source or Header  |  1992-12-19  |  14.9 KB  |  521 lines

  1. /* 
  2.  * devRaid.c --
  3.  *
  4.  *    This module implements the BlockDevice interface for
  5.  *    RAID level 5 disk arrays.
  6.  *    Assuming a minimum sector size of 512 bytes, RAID devices with an
  7.  *    address space of upto 2^40 bytes (~1 terra byte) are supported by
  8.  *    this driver.
  9.  *
  10.  * Copyright 1989 Regents of the University of California
  11.  * All rights reserved.
  12.  * Permission to use, copy, modify, and distribute this
  13.  * software and its documentation for any purpose and without
  14.  * fee is hereby granted, provided that the above copyright
  15.  * notice appear in all copies.  The University of California
  16.  * makes no representations about the suitability of this
  17.  * software for any purpose.  It is provided "as is" without
  18.  * express or implied warranty.
  19.  */
  20.  
  21. #ifndef lint
  22. static char rcsid[] = "$Header: /cdrom/src/kernel/Cvsroot/kernel/raid/devRaid.c,v 1.17 92/06/25 17:20:52 eklee Exp $ SPRITE (Berkeley)";
  23. #endif /* not lint */
  24.  
  25. #include "sync.h"
  26. #include <sprite.h>
  27. #include <stdio.h>
  28. #include <string.h>
  29. #include <dev/raid.h>
  30. #include "fs.h"
  31. #include "dev.h"
  32. /*
  33. #include "devDiskLabel.h"
  34. #include "devDiskStats.h"
  35. */
  36. #include "devBlockDevice.h"
  37. #include "devRaid.h"
  38. #include "devRaidUtil.h"
  39. #include "semaphore.h"
  40. #include "devRaidLog.h"
  41. #include "stdlib.h"
  42. #include "dbg.h"
  43. #include "devRaidProto.h"
  44.  
  45. static ReturnStatus StripeBlockIOProc();
  46. static ReturnStatus RaidBlockIOProc();
  47. static ReturnStatus ReleaseProc();
  48. static ReturnStatus IOControlProc();
  49.  
  50. /*
  51.  * A RAID device must have a minor number between 0 and 31 inclusive.
  52.  */
  53. Raid raidArray[] = {
  54.     {RAID_INVALID, Sync_SemInitStatic("devRaid.c: RAID unit 0")},
  55.     {RAID_INVALID, Sync_SemInitStatic("devRaid.c: RAID unit 1")},
  56.     {RAID_INVALID, Sync_SemInitStatic("devRaid.c: RAID unit 2")},
  57.     {RAID_INVALID, Sync_SemInitStatic("devRaid.c: RAID unit 3")},
  58.     {RAID_INVALID, Sync_SemInitStatic("devRaid.c: RAID unit 4")},
  59.     {RAID_INVALID, Sync_SemInitStatic("devRaid.c: RAID unit 5")},
  60.     {RAID_INVALID, Sync_SemInitStatic("devRaid.c: RAID unit 6")},
  61.     {RAID_INVALID, Sync_SemInitStatic("devRaid.c: RAID unit 7")},
  62.     {RAID_INVALID, Sync_SemInitStatic("devRaid.c: RAID unit 8")},
  63.     {RAID_INVALID, Sync_SemInitStatic("devRaid.c: RAID unit 9")},
  64.     {RAID_INVALID, Sync_SemInitStatic("devRaid.c: RAID unit 10")},
  65.     {RAID_INVALID, Sync_SemInitStatic("devRaid.c: RAID unit 11")},
  66.     {RAID_INVALID, Sync_SemInitStatic("devRaid.c: RAID unit 12")},
  67.     {RAID_INVALID, Sync_SemInitStatic("devRaid.c: RAID unit 13")},
  68.     {RAID_INVALID, Sync_SemInitStatic("devRaid.c: RAID unit 14")},
  69.     {RAID_INVALID, Sync_SemInitStatic("devRaid.c: RAID unit 15")},
  70.     {RAID_INVALID, Sync_SemInitStatic("devRaid.c: RAID unit 16")},
  71.     {RAID_INVALID, Sync_SemInitStatic("devRaid.c: RAID unit 17")},
  72.     {RAID_INVALID, Sync_SemInitStatic("devRaid.c: RAID unit 18")},
  73.     {RAID_INVALID, Sync_SemInitStatic("devRaid.c: RAID unit 19")},
  74.     {RAID_INVALID, Sync_SemInitStatic("devRaid.c: RAID unit 20")},
  75.     {RAID_INVALID, Sync_SemInitStatic("devRaid.c: RAID unit 21")},
  76.     {RAID_INVALID, Sync_SemInitStatic("devRaid.c: RAID unit 22")},
  77.     {RAID_INVALID, Sync_SemInitStatic("devRaid.c: RAID unit 23")},
  78.     {RAID_INVALID, Sync_SemInitStatic("devRaid.c: RAID unit 24")},
  79.     {RAID_INVALID, Sync_SemInitStatic("devRaid.c: RAID unit 25")},
  80.     {RAID_INVALID, Sync_SemInitStatic("devRaid.c: RAID unit 26")},
  81.     {RAID_INVALID, Sync_SemInitStatic("devRaid.c: RAID unit 27")},
  82.     {RAID_INVALID, Sync_SemInitStatic("devRaid.c: RAID unit 28")},
  83.     {RAID_INVALID, Sync_SemInitStatic("devRaid.c: RAID unit 29")},
  84.     {RAID_INVALID, Sync_SemInitStatic("devRaid.c: RAID unit 30")},
  85.     {RAID_INVALID, Sync_SemInitStatic("devRaid.c: RAID unit 31")},
  86. };
  87. int numRaid = sizeof(raidArray)/sizeof(Raid);
  88.  
  89.  
  90. /*
  91.  *----------------------------------------------------------------------
  92.  *
  93.  * DevRaidAttach --
  94.  *
  95.  *    Attach a RAID logical device.
  96.  *
  97.  * Results:
  98.  *    The DevBlockDeviceHandle of the device.
  99.  *
  100.  * Side effects:
  101.  *    Modifies raidArray data structure.
  102.  *
  103.  *----------------------------------------------------------------------
  104.  */
  105.  
  106. DevBlockDeviceHandle *
  107. DevRaidAttach(devicePtr)
  108.     Fs_Device    *devicePtr;    /* The device to attach. */
  109. {
  110.     RaidHandle    *handlePtr;
  111.     Raid    *raidPtr;
  112.     int        raidIndex;
  113.  
  114.     raidIndex = devicePtr->unit >> 4;
  115.     if ( raidIndex >= numRaid ) {
  116.         return (DevBlockDeviceHandle *) NIL;
  117.     }
  118.     raidPtr = &raidArray[raidIndex];
  119.     MASTER_LOCK(&raidPtr->mutex);
  120.     if ( raidPtr->state == RAID_INVALID ) {
  121.     raidPtr->state = RAID_ATTACHED;
  122.     MASTER_UNLOCK(&raidPtr->mutex);
  123. #ifdef TESTING
  124.     Sync_CondInit(&raidPtr->waitExclusive);
  125.     Sync_CondInit(&raidPtr->waitNonExclusive);
  126. #endif TESTING
  127.     Raid_InitStripeLocks();
  128.     InitDebugMem();
  129.     raidPtr->devicePtr = devicePtr;
  130.     Raid_Lock(raidPtr);
  131.     } else {
  132.     MASTER_UNLOCK(&raidPtr->mutex);
  133.     }
  134.  
  135.     handlePtr = (RaidHandle *) malloc(sizeof(RaidHandle));
  136.     /*
  137.      * 'S' means data striping only, no parity.
  138.      * We use a different blockIOproc to support this function.
  139.      */
  140.     handlePtr->blockHandle.blockIOProc = RaidBlockIOProc;
  141.     handlePtr->blockHandle.releaseProc = ReleaseProc;
  142.     handlePtr->blockHandle.IOControlProc = IOControlProc;
  143.     /*
  144.      * The problem is that we don't know the actual minTransferUnit when the
  145.      * RAID device is attached but only when the RAID_CONFIGURE IOC is
  146.      * performed after it's attached.
  147.      */
  148. /*
  149.     handlePtr->blockHandle.minTransferUnit = 1 << raidPtr->logBytesPerSector;
  150. */
  151. #ifdef TESTING
  152.     handlePtr->blockHandle.minTransferUnit = 4;
  153. #else
  154.     handlePtr->blockHandle.minTransferUnit = 512;
  155. #endif /* TESTING */
  156.     handlePtr->blockHandle.maxTransferSize = RAID_MAX_XFER_SIZE;
  157.     handlePtr->devPtr = devicePtr;
  158.     handlePtr->raidPtr = raidPtr;
  159.  
  160.     return (DevBlockDeviceHandle *) handlePtr;
  161. }
  162.  
  163.  
  164. /*
  165.  *----------------------------------------------------------------------
  166.  *
  167.  * ReleaseProc --
  168.  *
  169.  *    Block device release proc.
  170.  *
  171.  * Results:
  172.  *    Return status.
  173.  *
  174.  * Side effects:
  175.  *    Frees device handle.
  176.  *
  177.  *----------------------------------------------------------------------
  178.  */
  179.  
  180. static ReturnStatus
  181. ReleaseProc(handlePtr)
  182.     RaidHandle    *handlePtr; /* Handle pointer of device. */
  183. {
  184.     /*
  185.      * Note:  Only the handle is deallocated.
  186.      * The Raid data structures are never deallocated and stay around forever.
  187.      */
  188.     free((char *) handlePtr);
  189.     return SUCCESS;
  190. }
  191.  
  192.  
  193. /*
  194.  *----------------------------------------------------------------------
  195.  *
  196.  * IOControlProc --
  197.  *
  198.  *      Do a special operation on a RAID device.
  199.  *
  200.  * Results:
  201.  *      None.
  202.  *
  203.  * Side effects:
  204.  *      Depends on operation.
  205.  *
  206.  *----------------------------------------------------------------------
  207.  */
  208.  
  209. typedef struct {
  210.     Sema     sema;
  211.     ReturnStatus status;
  212. } IOCControl;
  213.  
  214. static void
  215. iocDoneProc(iocCtrlPtr, status)
  216.     IOCControl    *iocCtrlPtr;
  217.     ReturnStatus status;
  218. {
  219.     printf("RAID:MSG:IOC completed.\n");
  220.     if (status != SUCCESS) {
  221.     printf("RAID:ERR:IOC failed.\n");
  222.     }
  223.     iocCtrlPtr->status = status;
  224.     UpSema(&iocCtrlPtr->sema);
  225. }
  226.  
  227. static ReturnStatus
  228. IOControlProc(handlePtr, ioctlPtr, replyPtr) 
  229.     DevBlockDeviceHandle    *handlePtr;
  230.     Fs_IOCParam            *ioctlPtr;
  231.     Fs_IOReply            *replyPtr;
  232. {
  233.     static char  *IObuf;
  234.     RaidHandle     *raidHandlePtr   = (RaidHandle *) handlePtr;
  235.     Raid         *raidPtr         = raidHandlePtr->raidPtr;
  236.     RaidIOCParam *raidIOCParamPtr = (RaidIOCParam *) ioctlPtr->inBuffer;
  237.     DevBlockDeviceRequest *requestPtr =
  238.         (DevBlockDeviceRequest *) ioctlPtr->inBuffer;
  239.     int          col;
  240.     int          row;
  241.     ReturnStatus  status;
  242.     IOCControl      iocCtrl;
  243.  
  244.     if (raidIOCParamPtr == (RaidIOCParam *) NIL) {
  245.     printf("RAID:MSG:IOControlProc IOC == NIL\n");
  246.     return FAILURE;
  247.     }
  248.     col = raidIOCParamPtr->col;
  249.     row = raidIOCParamPtr->row;
  250.  
  251.     bzero((char *) replyPtr, sizeof(Fs_IOReply));
  252.  
  253.     switch(ioctlPtr->command) {
  254.     case IOC_DEV_RAID_PRINT:
  255.     if (raidPtr->state != RAID_VALID) {
  256.         return SUCCESS;
  257.     }
  258.     PrintRaid(raidPtr);
  259.     return SUCCESS;
  260.     case IOC_DEV_RAID_RECONFIG:
  261.     status = Raid_Configure(raidPtr, raidIOCParamPtr->buf);
  262.     return status;
  263.     case IOC_DEV_RAID_FAIL:
  264.     if (raidPtr->state != RAID_VALID) {
  265.         return FAILURE;
  266.     }
  267.     if (row < 0 || row >= raidPtr->numRow) {
  268.         printf("RAID:MSG:row=%d out of range on ioctl call", row);
  269.         return FAILURE;
  270.     }
  271.     if (col < 0 || col >= raidPtr->numCol) {
  272.         printf("RAID:MSG:col=%d out of range on ioctl call", col);
  273.         return FAILURE;
  274.     }
  275.     Raid_FailDisk(raidPtr, col, row, raidPtr->disk[col][row]->version);
  276.     return SUCCESS;
  277.     case IOC_DEV_RAID_REPLACE:
  278.     if (raidPtr->state != RAID_VALID) {
  279.         return FAILURE;
  280.     }
  281.     if (row < 0 || row >= raidPtr->numRow) {
  282.         printf("RAID:MSG:row=%d out of range on ioctl call", row);
  283.         return FAILURE;
  284.     }
  285.     if (col < 0 || col >= raidPtr->numCol) {
  286.         printf("RAID:MSG:col=%d out of range on ioctl call", col);
  287.         return FAILURE;
  288.     }
  289.     Raid_ReplaceDisk(raidPtr, col, row, raidPtr->disk[col][row]->version,
  290.         raidIOCParamPtr->type, raidIOCParamPtr->unit, 0);
  291.     return SUCCESS;
  292.     case IOC_DEV_RAID_HARDINIT:
  293.     if (raidPtr->state != RAID_VALID) {
  294.         return FAILURE;
  295.     }
  296.     InitSema(&iocCtrl.sema, "Raid HardInit", 0);
  297.     Raid_InitiateHardInit(raidPtr,
  298.         raidIOCParamPtr->startStripe, raidIOCParamPtr->numStripe,
  299.         iocDoneProc, (ClientData) &iocCtrl,
  300.         raidIOCParamPtr->ctrlData);
  301.     DownSema(&iocCtrl.sema);
  302.     return iocCtrl.status;
  303.     case IOC_DEV_RAID_PARITYCHECK:
  304.     if (raidPtr->state != RAID_VALID) {
  305.         return FAILURE;
  306.     }
  307.     InitSema(&iocCtrl.sema, "Raid ParityCheck", 0);
  308.     Raid_InitiateParityCheck(raidPtr,
  309.         raidIOCParamPtr->startStripe, raidIOCParamPtr->numStripe,
  310.         iocDoneProc, (ClientData) &iocCtrl,
  311.         raidIOCParamPtr->ctrlData);
  312.     DownSema(&iocCtrl.sema);
  313.     return iocCtrl.status;
  314.     case IOC_DEV_RAID_RECONSTRUCT:
  315.     if (raidPtr->state != RAID_VALID) {
  316.         return FAILURE;
  317.     }
  318.     InitSema(&iocCtrl.sema, "Raid Reconstruct", 0);
  319.     Raid_InitiateReconstruction(raidPtr, col, row,
  320.         raidPtr->disk[col][row]->version,
  321.         raidIOCParamPtr->numStripe, raidIOCParamPtr->uSec,
  322.         iocDoneProc, (ClientData) &iocCtrl,
  323.         raidIOCParamPtr->ctrlData);
  324.     DownSema(&iocCtrl.sema);
  325.     return iocCtrl.status;
  326.     case IOC_DEV_RAID_IO:
  327.     if (raidPtr->state != RAID_VALID) {
  328.         return FAILURE;
  329.     }
  330.     if (!IObuf) {
  331.         IObuf = (char *) malloc(1024*1024);
  332.     }
  333.     requestPtr->buffer = IObuf;
  334.     return Dev_BlockDeviceIOSync(handlePtr, requestPtr,
  335.         (int *)ioctlPtr->outBuffer);
  336.     case IOC_DEV_RAID_LOCK:
  337.     Raid_Lock(raidPtr);
  338.     return SUCCESS;
  339.     case IOC_DEV_RAID_UNLOCK:
  340.     Raid_Unlock(raidPtr);
  341.     return SUCCESS;
  342.     case IOC_DEV_RAID_SAVE_STATE:
  343.     if (raidPtr->state != RAID_VALID) {
  344.         return FAILURE;
  345.     }
  346.     status = Raid_SaveState(raidPtr);
  347.     if (status != SUCCESS) {
  348.         printf("RAID:MSG:Could not save state.\n");
  349.     }
  350.     return status;
  351.     case IOC_DEV_RAID_ENABLE_LOG:
  352.     Raid_EnableLog(raidPtr);
  353.     return SUCCESS;
  354.     case IOC_DEV_RAID_DISABLE_LOG:
  355.     Raid_DisableLog(raidPtr);
  356.     return SUCCESS;
  357.     case IOC_DEV_RAID_RESTORE_STATE:
  358.     status = Raid_RestoreState(raidPtr, raidIOCParamPtr->type,
  359.         raidIOCParamPtr->unit, raidIOCParamPtr->startStripe);
  360.     if (status != SUCCESS) {
  361.         printf("RAID:MSG:Could not restore state.\n");
  362.     }
  363.     return status;
  364.     case IOC_DEV_RAID_DISABLE:
  365.     Raid_Disable(raidPtr);
  366.     return SUCCESS;
  367.     case IOC_DEV_RAID_ENABLE:
  368.     Raid_Enable(raidPtr);
  369.     return SUCCESS;
  370.     default:
  371.     return SUCCESS;
  372.     }
  373. }
  374.  
  375.  
  376. /*
  377.  *----------------------------------------------------------------------
  378.  *
  379.  * StripeBlockIOProc --
  380.  *    Perform block IO w/o parity, i.e. data striping only,
  381.  *    on specified RAID device.
  382.  *
  383.  * Results:
  384.  *    None.
  385.  *
  386.  * Side effects:
  387.  *    The disk write, if operation == FS_WRITE.
  388.  *
  389.  *----------------------------------------------------------------------
  390.  */
  391. static ReturnStatus
  392. StripeBlockIOProc(handlePtr, requestPtr) 
  393.     DevBlockDeviceHandle  *handlePtr;
  394.     DevBlockDeviceRequest *requestPtr;
  395. {
  396.     RaidHandle       *raidHandlePtr;
  397.     Raid        *raidPtr;
  398.     unsigned         firstSector;
  399.     unsigned        nthSector;
  400.     unsigned        numSector;
  401.  
  402.     raidHandlePtr = (RaidHandle *) handlePtr;
  403.     raidPtr      = raidHandlePtr->raidPtr;
  404.  
  405.     /*
  406.      * Check if operation valid.
  407.      */
  408.     if (!((requestPtr->operation == FS_READ) ||
  409.           (requestPtr->operation == FS_WRITE))) {
  410.     panic("Unknown operation %d in RAID blockIOProc.\n", 
  411.         requestPtr->operation);
  412.     return DEV_INVALID_ARG;
  413.     }
  414.  
  415.     /*
  416.      * Convert byte addresses to sector addresses.
  417.      */
  418.     firstSector = (requestPtr->startAddress >> raidPtr->logBytesPerSector) |
  419.         (requestPtr->startAddrHigh<<(BITS_PER_ADDR-raidPtr->logBytesPerSector));
  420.     numSector = requestPtr->bufferLen >> raidPtr->logBytesPerSector;
  421.     nthSector = firstSector + numSector;
  422.  
  423.     /*
  424.      * Check that addresses are within the range supported by the device.
  425.      */
  426.     if ( firstSector >= raidPtr->numSector ) {
  427.     requestPtr->doneProc(requestPtr, FAILURE, 0);
  428.     return SUCCESS;
  429.     } 
  430.  
  431.     /*
  432.      * Prevent overruns.
  433.      */
  434.     if ( nthSector > raidPtr->numSector ) {
  435.         nthSector = raidPtr->numSector;
  436.     } 
  437.  
  438.     Raid_InitiateSimpleStripeIOs(raidPtr, requestPtr->operation,
  439.             firstSector, nthSector, requestPtr->buffer,
  440.             requestPtr->doneProc, (ClientData) requestPtr,
  441.             requestPtr->ctrlData[0]);
  442.     return SUCCESS;
  443. }
  444.  
  445.  
  446. /*
  447.  *----------------------------------------------------------------------
  448.  *
  449.  * RaidBlockIOProc --
  450.  *
  451.  *    Perform block IO (w/ parity) on specified RAID device.
  452.  *
  453.  * Results:
  454.  *    None.
  455.  *
  456.  * Side effects:
  457.  *    The disk write, if operation == FS_WRITE.
  458.  *
  459.  *----------------------------------------------------------------------
  460.  */
  461.  
  462. static ReturnStatus
  463. RaidBlockIOProc(handlePtr, requestPtr) 
  464.     DevBlockDeviceHandle  *handlePtr;
  465.     DevBlockDeviceRequest *requestPtr;
  466. {
  467.     RaidHandle       *raidHandlePtr;
  468.     Raid        *raidPtr;
  469.     unsigned         firstSector;
  470.     unsigned        nthSector;
  471.     unsigned        numSector;
  472.  
  473.     raidHandlePtr = (RaidHandle *) handlePtr;
  474.     raidPtr      = raidHandlePtr->raidPtr;
  475.  
  476.     /*
  477.      * If striping only (no parity) use the the simpler routine.
  478.      */
  479.     if (raidPtr->parityConfig == 'S') {
  480.     return StripeBlockIOProc(handlePtr, requestPtr);
  481.     }
  482.     /*
  483.      * Check if operation valid.
  484.      */
  485.     if (!((requestPtr->operation == FS_READ) ||
  486.           (requestPtr->operation == FS_WRITE))) {
  487.     panic("Unknown operation %d in RAID blockIOProc.\n", 
  488.         requestPtr->operation);
  489.     return DEV_INVALID_ARG;
  490.     }
  491.  
  492.     /*
  493.      * Convert byte addresses to sector addresses.
  494.      */
  495.     firstSector = (requestPtr->startAddress >> raidPtr->logBytesPerSector) |
  496.         (requestPtr->startAddrHigh<<(BITS_PER_ADDR-raidPtr->logBytesPerSector));
  497.     numSector = requestPtr->bufferLen >> raidPtr->logBytesPerSector;
  498.     nthSector = firstSector + numSector;
  499.  
  500.     /*
  501.      * Check that addresses are within the range supported by the device.
  502.      */
  503.     if ( firstSector >= raidPtr->numSector ) {
  504.     requestPtr->doneProc(requestPtr, FAILURE, 0);
  505.     return SUCCESS;
  506.     } 
  507.  
  508.     /*
  509.      * Prevent overruns.
  510.      */
  511.     if ( nthSector > raidPtr->numSector ) {
  512.         nthSector = raidPtr->numSector;
  513.     } 
  514.  
  515.     Raid_InitiateStripeIOs(raidPtr, requestPtr->operation,
  516.             firstSector, nthSector, requestPtr->buffer,
  517.             requestPtr->doneProc, (ClientData) requestPtr,
  518.             requestPtr->ctrlData[0]);
  519.     return SUCCESS;
  520. }
  521.